#ifndef WORLD_H_INCLUDED
#define WORLD_H_INCLUDED

#include "Common.h"

class Monster;
class Item;

class MapBase
{
public:
    MapBase() : m_bg(NULL), m_blit(true) {}
    virtual ~MapBase() { if (m_bg) delete m_bg; }
    virtual bool loadMap(const char *filename) = 0;
    virtual bool isValidPoint(const Rect &rect) = 0;
    virtual void draw(BITMAP *surface) = 0;
    virtual void drawMiniMap(BITMAP *surface) = 0;
    virtual BITMAP *getmapbmp() const = 0;
    virtual BITMAP *getminimapbmp() const = 0;
    inline void setbg (MapBase *bg)  { m_bg = bg; bg->m_blit = false;}
    inline MapBase * getbg () const { return m_bg; }
    inline bool need_blit() const { return m_blit; }
private:
    MapBase *m_bg;
    bool     m_blit;
};

class BackGroudMap : public MapBase
{
    struct Cell {
        Cell() : m_off(-1), m_tile(NULL), m_mini_color(0) {}

        char           m_off;
        BITMAP        *m_tile;
        size_t         m_mini_color;
    };
public:
    BackGroudMap();
    ~BackGroudMap();
    bool loadMap(const char *filename);
    bool isValidPoint(const Rect &rect);
    void draw(BITMAP *surface);
    void drawMiniMap(BITMAP *surface);
    BITMAP *getmapbmp() const { return m_mapbmp; }
    BITMAP *getminimapbmp() const { return m_minimap; }
private:
    Cell    m_map[MAP_H][MAP_W];
    BITMAP *m_mapbmp;
    BITMAP *m_minimap;
};

class MonsterMap : public MapBase
{
public:
    MonsterMap();
    ~MonsterMap();

    bool loadMap(const char *filename);
    bool isValidPoint(const Rect &rect);
    void draw(BITMAP *surface);
    void drawMiniMap(BITMAP *surface);
    BITMAP *getmapbmp() const { return getbg() ? getbg()->getmapbmp() : NULL; }
    BITMAP *getminimapbmp() const { return getbg() ? getbg()->getminimapbmp() : NULL; }

    Monster *get(short x, short y);
    bool put(Monster *monster, short x, short y);
    void remove(short x, short y);
    void clean();

private:
    Monster *m_map[MAP_H][MAP_W];
};

class ItemMap : public MapBase
{
    enum { ITEM_MAX = 2 };
public:
    ItemMap();
    ~ItemMap();

    bool loadMap(const char *filename);
    bool isValidPoint(const Rect &rect);
    void draw(BITMAP *surface);
    void drawMiniMap(BITMAP *surface);
    BITMAP *getmapbmp() const { return getbg() ? getbg()->getmapbmp() : NULL; }
    BITMAP *getminimapbmp() const { return getbg() ? getbg()->getminimapbmp() : NULL; }

    Item *get(short x, short y, short n = 0);
    bool put(Item *item, short x, short y);
    bool remove(short x, short y, short n);
    bool remove(short x, short y, Item *item);
    void clean();

private:
    bool _put(Item *item, short x, short y);
    Item *m_map[MAP_H][MAP_W][2];
};

class MapVisitor
{
public:
    bool put_monster(Monster *m, MapBase *mb, short x, short y);
    bool put_item(Item *m, MapBase *mb, short x, short y);
};

namespace test
{
    extern MapBase *g_map;
};

#endif // WORLD_H_INCLUDED
